require(
	[
		"jquery", "webgl", "assetSyst", 
		"assetShader", "assetShaderProgram", "jsonModel", 
		"cam", "transform", "timer", 
		"renderer", "material", "camOrbit",
		"input", "textRenderer", "bitmapFont",
		"texture", "bitmapFontRenderer", "objectPool",
		"osmparser/areaParser", "render/bufferMaker", "geom/polygon",
		"glMatrix"
	], 
	function(
		$, webgl, assetSyst, 
		assetShader, asp, jsonModel, 
		cam, transform, timer, 
		renderer, material, camOrbit,
		input, textRenderer, bitmapFont,
		texture, bitmapFontRenderer, objectPool,
		areaParser, bufferMaker, polygon
	) {
	
		var entities;
		var ttimer;
		var frame = 0;
		var rr;
		var textR;
		var bmfR;
		var camBehavior;
		var t;
		
		function tick() {
			//
			++frame;
		
			//update
			ttimer.update();
			camBehavior.update(ttimer);
			animate();
			input.update();
			if(t) {
				//var txt = "" + Math.ceil(Math.random() * 1000);
				//t.setText(txt);
				t.transform.rot[0] += ttimer.lastDelta();
				//t.transform.update();
			}
			
			//render
			rr.render();
			//bmfR.render();
			
			requestAnimFrame(tick);
		}
		
		function printFPS() {
			$("#FPS").text("FPS : " + frame);
			frame = 0;
		}
		
		function createBuilding() {			
			//load building
			var data = [
				0, 0,
				0, 1,
				1, 1,
				1, 0
			]
			
			//build 3d vertex and indices for building
			var vertices = [ ];  
			var indices = [ ]  
			var height = 1;
			
			//build walls
			for(var i = 0; i < data.length; i+=2) {
				vertices.push(data[i], 0, data[i+1]);
			}
			for(var i = 0; i < data.length; i+=2) {
				vertices.push(data[i], height, data[i+1]);
			}
			
			var n 	= data.length/2;
			var vlen= vertices.length/3;
			for(var i = 0; i < n; ++i) {
				indices.push(
					i, i+n, (i+1)%n,
					i+n, ((i+1)%n)+n, (i+1)%n
				)
			}
			
			//build roof
			var p = polygon.create();
			p.addVertices(data);
			var idx = p.triangulate();
			for(var i = 0; i < idx.length; ++i) {
				indices.push(idx[i]+n);
			}
			
			//push them to VBO
			vBuf = webgl.createStaticBuf(webgl.gl.ARRAY_BUFFER, Float32Array, vertices, 3);
			iBuf = webgl.createStaticBuf(webgl.gl.ELEMENT_ARRAY_BUFFER, Uint16Array, indices, 1);
		}
		
		var osmProcessed = false;
		var shader;
		var vBuf;
		var iBuf;
		var ccam;
		
		function tick2() {
			if(!shader.isLoaded() || !osmProcessed) {
				requestAnimFrame(tick2);
				return;
			}
			
			//update
			ttimer.update();
			camBehavior.update(ttimer);
			input.update(ttimer);
		
			////draw them
			//clear screen & depth
			var gl = webgl.gl;
			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
			
			//apply shader
			gl.useProgram(shader.program);
			
			//apply cam transform
			gl.uniformMatrix4fv(shader.getUniform("uVMat"), false, ccam.getView());
			gl.uniformMatrix4fv(shader.getUniform("uPMat"), false, ccam.getPerspective());	
			
			//apply model vertices & transform
			webgl.pointAttrib(shader.getAttribute("aPos"), vBuf);
			
			//draw call
			gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, iBuf);
			gl.drawElements(gl.TRIANGLES, iBuf.numItems, gl.UNSIGNED_SHORT, 0);
			
			requestAnimFrame(tick2);
		}
		
		function createBuilding2(verts, indices) {
			vBuf = webgl.createStaticBuf(webgl.gl.ARRAY_BUFFER, Float32Array, verts, 3);
			iBuf = webgl.createStaticBuf(webgl.gl.ELEMENT_ARRAY_BUFFER, Uint16Array, indices, 1);
		}
		
		function processOSM(xml) {
			var buildings = areaParser.parseOSM(xml);
			var verts = [];
			var indcs = [];
			for(var j = 0; j < buildings.length; ++j) {
				var b = buildings[j];
					
				var n = b.indices.length;
				var nn = verts.length/3;
				for(var i = 0; i < n; ++i) {
					indcs.push(b.indices[i] + nn);
				}
				
				for(var i = 0; i < b.verts.length; ++i)
					verts.push(b.verts[i]);
			}
			
			createBuilding2(verts, indcs);
			osmProcessed = true;
		}
	
		$(function() {
			//Init webgl
			if(!webgl.init($('canvas')[0], true)) return;
		
			//asset mapping
			assetSyst.mapExt("shader", "shader/", assetShader);
			assetSyst.mapExt("json", "model/", jsonModel);
			assetSyst.mapExt("material", "material/", material);
			assetSyst.mapExt("fnt", "fnt/", bitmapFont);
			assetSyst.mapExt("png", "img/", texture);
			assetSyst.mapExt("sp", "", asp);
			
			//init camera
			ccam = cam.create();
			ccam.pos = vec3.create([40, 20, 40]);
			ccam.target = vec3.create([13, 0, 24]);
			ccam.aspect = webgl.viewportWidth / webgl.viewportHeight;
			ccam.update();
			
			//
			ttimer = timer.create();
			camBehavior = camOrbit.create(ccam);
			
			//input init
			input.init($('canvas'), ttimer);
			
			//load shader
			shader = assetSyst.get("vBasic|fBasic|shader.sp", function() { });
			$.get("osm/map.osm", null, processOSM, "xml");
			//createBuilding();
			tick2();
		});
});
